﻿using System.Linq;
using CardPlay.Model.ActionModel;
using CardPlay.Model.CardModel;
using CardPlay.Model.GameModel;
using CardPlay.Model.GameModel.Actions;
using CardPlay.Model.GameModel.Presentation;
using CardPlay.Model.Layout;

namespace CardPlay.DemoPack.Games.SlyFoxVariants
{
    [Game("A6BF8F08-4779-43F2-B3C6-C08ABD7A8445", LevelOfDifficulty.Medium, LevelOfSkill.MostlySkill, DurationOfPlay.MoreThan10Minutes, NumberOfDecks = 2, Family = FamilyName)]
    public class SlyFox : TwentyBase
    {
        public SlyFox()
        {
            PreprocessAction = AugmentMovePileAction;
        }

        protected override void PrepareStockPresentation(IPresentationContext presentation, SideBySideLayout stockWasteColumn)
        {
            var stockStyle = presentation.StyleForStock(this);
            stockStyle.EmptyCue = () => EmptyPileCue.None;

            var wasteStyle = new VisualTraits
            {
                Arrangement = CardArrangement.StackTower,
                ContentFit = ContentFit.FitBounds,
                EmptyCue = () => this[Stock].IsEmpty ? EmptyPileCue.None : EmptyPileCue.Redeal
            };

            stockWasteColumn.Add(presentation.CreatePileVisual(Stock, stockStyle));
            stockWasteColumn.Add(presentation.CreatePileVisual(NameOfDealTarget, wasteStyle));
        }

        protected override void PrepareDealScript(DealScript script)
        {
            script.DealAcesTo(StandardPileNames.Foundations.Take(4));
            script.DealRankTo(StandardPileNames.Foundations.Skip(4).Take(4), Rank.King);
            script.DealToEach(NamesOfTableaus, "up");
            script.DealRemainingFaceDownTo(Stock);
        }

        protected override void OverridePlayingRules(PlayingRules playingRules)
        {
            playingRules.At(Stock).ConditionallyPermit<DealAction>(action => this[NameOfDealTarget].IsEmpty);
            playingRules.At(AnyTableau).ConditionallyPermit<MovePileAction>(action => action.SourcePile.Location.Matches(NameOfDealTarget));
        }

        protected override bool AllowedToBuildFoundation(MovePileAction action)
        {
            return (!IsTableauDirty || this[NameOfDealTarget].IsEmpty) && base.AllowedToBuildFoundation(action);
        }

        protected override IAction QueryActionAt(PartLocation location)
        {
            if (location.Path != Stock) return base.QueryActionAt(location);

            var dealTarget = this[NameOfDealTarget];
            if (location.Index < 0 || dealTarget == null) return null;

            GameAction action = new DealAction(this, location, dealTarget.Location);
            return Regulations.Permit(action) ? action : null;
        }

        protected override void OnTransactionEnding()
        {
            if (!IsTableauDirty) this.FillFromStockEmptyPilesMatching(AnyTableau);
        }

        protected bool IsTableauDirty { get; set; }

        private IAction AugmentMovePileAction(IAction action)
        {
            if (IsTableauDirty) return action;

            var movePileAction = action as MovePileAction;
            if (movePileAction == null || !movePileAction.TargetPile.Location.Matches(AnyTableau)) return action;

            return new ComplexAction
            {
                action,
                new DelegatingAction
                {
                    OnExecute = () => IsTableauDirty = true,
                    OnReverse = () => IsTableauDirty = false
                }
            };
        }
    }
}
